package com.match.util;

import com.match.entry.Mail;
import com.match.entry.MailAttach;

import javax.mail.*;
import javax.mail.internet.MimeUtility;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.*;

public class ReceiveMailUtil {
    private final static String FILE_URL = "E:\\";
    private final static String excel2003L = ".xls";    //2003- 版本的excel
    private final static String excel2007U = ".xlsx";   //2007+ 版本的excel

    /**
     * @param mail
     * @param read 已经读到的邮件数目
     * @return
     */
    public static List<Mail> recipient(Mail mail, Integer read) {
        Session session = MailSessionUtil.createSessionUtil(mail);
        session.setDebug(false);
        /*
         * Store类实现特定邮件协议上的读、写、监视、查找等操作。
         * 通过Store类可以访问Folder类。
         * Folder类用于分级组织邮件，并提供照Message格式访问email的能力。
         */
        Store store = null;
        Folder folder = null;
        List<Mail> receiveList = new ArrayList<>();
        try {
            store = session.getStore(mail.getProtocol());
            store.connect(mail.getUserName(), mail.getPassword());

            folder = store.getFolder("INBOX");
            folder.open(Folder.READ_WRITE);//打开收件箱
//            folder.open(Folder.READ_ONLY);//打开收件箱
            // 由于POP3协议无法获知邮件的状态,所以getUnreadMessageCount得到的是收件箱的邮件总数
            int unread = folder.getUnreadMessageCount();
            System.out.println("未读邮件数: " + unread);
//            // 由于POP3协议无法获知邮件的状态,所以下面得到的结果始终都是为0
            System.out.println("删除邮件数: " + folder.getDeletedMessageCount());
            System.out.println("新邮件: " + folder.getNewMessageCount());
//            // 获得收件箱中的邮件总数
            System.out.println("邮件总数: " + folder.getMessageCount());


            int size = folder.getMessageCount();//获取邮件数目
            //获取邮件
            for (int i = read + 1; i <= size; i++) {
                Message message = folder.getMessage(i);
                //解析邮件内容
                String from = message.getFrom()[0].toString();
                String subject = message.getSubject();
                Date date = message.getSentDate();
                Mail receiveMail = new Mail();
                if (!(message.getContent() instanceof String)) {
                    parseMultipart((Multipart) message.getContent(), receiveMail);
                }
                receiveMail.setFromEmail(getSubChinese(from));
                receiveMail.setSubject(subject);
                receiveMail.setDate(date);
                receiveList.add(receiveMail);
            }

            System.out.println("接收成功！");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (folder != null) {
                    folder.close(false);
                }
                if (store != null) {
                    store.close();
                }
            } catch (Exception e) {
                System.out.println("接收失败！");
                e.printStackTrace();
            }
        }

        System.out.println("接收完毕！");
        return receiveList;
    }

    /**
     * 对复杂邮件的解析
     *
     * @param multipart
     * @param receiveMail
     * @throws MessagingException
     * @throws IOException
     */
    private static Mail parseMultipart(Multipart multipart, Mail receiveMail) throws MessagingException, IOException {

        List<MailAttach> contentList = new ArrayList<>();
        List<MailAttach> attachList = new ArrayList<>();
        int count = multipart.getCount();
//        System.out.println("count =  " + count);
        for (int idx = 0; idx < count; idx++) {
            BodyPart bodyPart = multipart.getBodyPart(idx);
            MailAttach attach = new MailAttach();
//            System.out.println(bodyPart.getContentType());
            if (bodyPart.isMimeType("text/plain")) {
                attach.setContent(bodyPart.getContent().toString());
                contentList.add(attach);
//                System.out.println("plain................." + bodyPart.getContent());
            } else if (bodyPart.isMimeType("text/html")) {
                attach.setContent(bodyPart.getContent().toString());
                contentList.add(attach);
//                System.out.println("html..................." + bodyPart.getContent());
            } else if (bodyPart.isMimeType("multipart/*")) {
                Multipart mpart = (Multipart) bodyPart.getContent();
                parseMultipart(mpart, receiveMail);
            } else if (bodyPart.isMimeType("application/octet-stream")) {
                String disposition = bodyPart.getDisposition();
//                System.out.println(disposition);
                if (disposition.equalsIgnoreCase(BodyPart.ATTACHMENT)) {
                    saveFile(bodyPart, attach);
                    attachList.add(attach);
                }
            } else if (bodyPart.isMimeType("image/jpeg")) {
                saveFile(bodyPart, attach);
                attach.setPic(true);
                attachList.add(attach);
            }

        }
        if (!contentList.isEmpty()) {
            receiveMail.setMailContentList(contentList);
        }
        if (!attachList.isEmpty()) {
            receiveMail.setMailAttachList(attachList);
        }
        return receiveMail;
    }

    /**
     * 保存文件到本地
     *
     * @param bodyPart
     * @param attach
     * @throws MessagingException
     * @throws IOException
     */
    private static void saveFile(BodyPart bodyPart, MailAttach attach) throws MessagingException, IOException {

        String fileName = getSubChinese(bodyPart.getFileName());
        boolean flag = isExcelFile(fileName);
        if (flag) {
            fileName = newFileName(fileName);
            InputStream is = bodyPart.getInputStream();
            String fileUrl = FILE_URL + fileName;
            copy(is, new FileOutputStream(fileUrl));
            attach.setFileName(fileUrl);
        } else {
            attach.setFileName(fileName);
        }
        attach.setExcel(flag);
    }

    /**
     * 转码
     *
     * @param str
     * @return
     */
    private static String getSubChinese(String str) {
        String rtnStr;
        try {
            if(str==null)
                return null;
            rtnStr = new String(str.getBytes(StandardCharsets.ISO_8859_1));
            if (rtnStr.contains("=")) {
                rtnStr = MimeUtility.decodeText(str);
            }
        } catch (UnsupportedEncodingException e) {
            rtnStr = str;
            e.printStackTrace();
        }
//        System.out.println(rtnStr);
        return rtnStr;
    }

    /**
     * 文件拷贝，在用户进行附件下载的时候，可以把附件的InputStream传给用户进行下载
     *
     * @param is
     * @param os
     * @throws IOException
     */
    private static void copy(InputStream is, OutputStream os) throws IOException {
        byte[] bytes = new byte[1024];
        int len;
        while ((len = is.read(bytes)) != -1) {
            os.write(bytes, 0, len);
        }
        if (os != null)
            os.close();
        is.close();
    }

    /**
     * 判断是否为excel
     *
     * @param fileName
     */
    private static boolean isExcelFile(String fileName) {
        if(fileName==null)
            return false;
        String fileType = fileName.substring(fileName.lastIndexOf("."));
        if (excel2003L.equals(fileType) || excel2007U.equals(fileType)) {
            return true;
        }
        return false;
    }

    /**
     * 保存文件增加时间戳表示
     *
     * @param fileName
     * @return
     */
    private static String newFileName(String fileName) {
        int index = fileName.lastIndexOf(".");
        String fileType = fileName.substring(index);
        fileName = fileName.substring(0, index);
        fileName = fileName + Calendar.getInstance().getTimeInMillis() + fileType;
        return fileName;
    }
}
